#pragma once 

#include "thread.hpp"
#include "lockGroud.hpp"
#include "Task.hpp"

#include <vector>
#include <queue>
#include <unistd.h>

using namespace ThreadNS;
static const int gnum = 5;

template<class T>
class ThreadPool;
template<class T>
class ThreadData    //大号结构体，方便我们传入线程的名字，后续再想传入一些内容可以在此添加
{
public:
    ThreadData(ThreadPool<T>* in,const string& name)
        :threadpool(in),_name(name)
        {}
public:
    ThreadPool<T>* threadpool;
    string _name;
};

template<class T>
class ThreadPool
{
public:
    ThreadPool(const int& num = gnum)
        :_num(num)
    {
        pthread_mutex_init(&_mutex,nullptr);    //初始化锁
        pthread_cond_init(&_cond,nullptr);      //初始化条件变量
        for(int i = 0;i<_num;++i)
        {
            _threads.push_back(new Thread());  //创建线程 
        }

    }
    void push(const T& in)
    {
        // pthread_mutex_lock(&_mutex); 
        lockGroud lockgroud(&_mutex);   //RAII的锁
        _Task_queue.push(in);           //给任务队列里插入任务
        pthread_cond_signal(&_cond);    //唤醒一个线程
        // pthread_mutex_unlock(&_mutex);
    }
    void run()
    {
        for(auto& t:_threads)
        {
            //将要传入执行方法的参数打包成结构体传入
            ThreadData<T>* td = new ThreadData<T>(this,t->threadname());   

            cout << t->threadname() << "  准备就绪" << endl;
            t->start(handlerTask,td);   //执行方法
        }
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);     //销毁锁
        pthread_cond_destroy(&_cond);       //销毁条件变量
        for(auto& t:_threads) delete t;     //销毁线程
    }
    T pop()
    {
        T t = _Task_queue.front();      //取任务
        _Task_queue.pop();              
        return t;
    }
    //一批接口
    pthread_mutex_t* Mutex(){ return &_mutex;}
    void threadlock() { pthread_mutex_lock(&_mutex); }
    void threadunlock() { pthread_mutex_unlock(&_mutex); }
    bool threadempty() { return _Task_queue.empty();}
    void threadwait() { pthread_cond_wait(&_cond,&_mutex);}
private:
    static void* handlerTask(void* args)
    {
        ThreadData<T>* td = static_cast<ThreadData<T>*>(args);
        // ThreadPool<T>* threadpool = static_cast<ThreadPool<T>*>(args);

        while(true)
        {
            T t;
            {
                // td->threadpool->threadlock();
                lockGroud lockgroud(td->threadpool->Mutex()); //RAII
                while(td->threadpool->threadempty())    //任务队列为空
                {
                    td->threadpool->threadwait();       //线程就挂起等待
                }
                t = td->threadpool->pop();              //获取任务
                // td->threadpool->threadunlock();
            }
            
            cout << td->_name << "获取任务，计算结果："<< t() << endl;            //执行任务
            // sleep(1);
        }
        return nullptr;
    }
private:
    int _num;                   //线程数量
    vector<Thread*> _threads;   //线程池
    queue<T> _Task_queue;       //任务队列
    pthread_mutex_t _mutex;     //互斥锁
    pthread_cond_t _cond;       //条件变量
};